<?php

namespace app\service;

use app\model\Account;
use app\model\Category;
use app\model\UserLog;
use Exception;

class ImportExportService
{
    /**
     * 导出账号数据为JSON格式
     */
    public function exportToJson($userId, $categoryId = null, $includeDecrypted = false)
    {
        $query = Account::where('user_id', $userId);

        if ($categoryId) {
            $query->where('category_id', $categoryId);
        }

        $accounts = $query->with(['category'])->select();

        $exportData = [
            'version' => '1.0',
            'export_time' => date('Y-m-d H:i:s'),
            'total_count' => count($accounts),
            'accounts' => []
        ];

        foreach ($accounts as $account) {
            $accountData = [
                'title' => $account->title,
                'username_encrypted' => $account->username_encrypted,
                'password_encrypted' => $account->password_encrypted,
                'website' => $account->website,
                'notes_encrypted' => $account->notes_encrypted,
                'icon' => $account->icon,
                'tags' => $account->tags,
                'encrypt_method' => $account->encrypt_method,
                'encrypt_version' => $account->encrypt_version,
                'expires_at' => $account->expires_at,
                'category_name' => $account->category ? $account->category->name : null,
                'created_at' => $account->created_at
            ];

            $exportData['accounts'][] = $accountData;
        }

        // 记录导出日志
        UserLog::record($userId, 'export_data', "导出账号数据: {$exportData['total_count']}条");

        return $exportData;
    }

    /**
     * 导出为CSV格式
     */
    public function exportToCsv($userId, $categoryId = null)
    {
        $query = Account::where('user_id', $userId);

        if ($categoryId) {
            $query->where('category_id', $categoryId);
        }

        $accounts = $query->with(['category'])->select();

        $csv = [];
        // CSV头部
        $csv[] = ['标题', '网址', '分类', '标签', '加密方式', '创建时间'];

        foreach ($accounts as $account) {
            $csv[] = [
                $account->title,
                $account->website,
                $account->category ? $account->category->name : '',
                $account->tags,
                $account->encrypt_method,
                $account->created_at
            ];
        }

        // 记录导出日志
        UserLog::record($userId, 'export_data', "导出CSV数据: " . (count($csv) - 1) . "条");

        return $csv;
    }

    /**
     * 从JSON导入账号数据
     */
    public function importFromJson($userId, $jsonData, $options = [])
    {
        // 验证数据格式
        if (!isset($jsonData['accounts']) || !is_array($jsonData['accounts'])) {
            throw new Exception('数据格式错误');
        }

        $skipDuplicates = $options['skip_duplicates'] ?? true;
        $updateExisting = $options['update_existing'] ?? false;

        $imported = 0;
        $skipped = 0;
        $errors = [];

        foreach ($jsonData['accounts'] as $accountData) {
            try {
                // 验证必填字段
                if (empty($accountData['title'])) {
                    $skipped++;
                    $errors[] = "跳过: 标题为空的账号";
                    continue;
                }

                // 检查是否存在重复
                $existing = Account::where('user_id', $userId)
                    ->where('title', $accountData['title'])
                    ->where('website', $accountData['website'] ?? '')
                    ->find();

                if ($existing) {
                    if ($skipDuplicates && !$updateExisting) {
                        $skipped++;
                        $errors[] = "跳过重复: {$accountData['title']}";
                        continue;
                    }

                    if ($updateExisting) {
                        // 更新现有账号
                        $this->updateAccountFromImport($existing, $accountData);
                        $imported++;
                        continue;
                    }
                }

                // 获取或创建分类
                $categoryId = null;
                if (!empty($accountData['category_name'])) {
                    $category = Category::where('name', $accountData['category_name'])
                        ->where(function ($query) use ($userId) {
                            $query->where('user_id', $userId)
                                ->whereOr('user_id', null);
                        })
                        ->find();

                    if ($category) {
                        $categoryId = $category->id;
                    }
                }

                // 创建新账号
                $newAccount = [
                    'user_id' => $userId,
                    'category_id' => $categoryId,
                    'title' => $accountData['title'],
                    'username_encrypted' => $accountData['username_encrypted'] ?? '',
                    'password_encrypted' => $accountData['password_encrypted'] ?? '',
                    'website' => $accountData['website'] ?? '',
                    'notes_encrypted' => $accountData['notes_encrypted'] ?? '',
                    'icon' => $accountData['icon'] ?? '',
                    'tags' => $accountData['tags'] ?? '',
                    'encrypt_method' => $accountData['encrypt_method'] ?? 'AES-256-GCM',
                    'encrypt_version' => $accountData['encrypt_version'] ?? '1.0',
                    'expires_at' => $accountData['expires_at'] ?? null,
                ];

                Account::create($newAccount);
                $imported++;

            } catch (Exception $e) {
                $skipped++;
                $errors[] = "导入失败 [{$accountData['title']}]: " . $e->getMessage();
            }
        }

        // 记录导入日志
        UserLog::record($userId, 'import_data', "导入账号数据: 成功{$imported}条, 跳过{$skipped}条");

        return [
            'imported' => $imported,
            'skipped' => $skipped,
            'errors' => $errors
        ];
    }

    /**
     * 从CSV导入账号数据
     */
    public function importFromCsv($userId, $csvData, $options = [])
    {
        if (empty($csvData) || count($csvData) < 2) {
            throw new Exception('CSV数据为空或格式错误');
        }

        // 跳过表头
        $headers = array_shift($csvData);

        $skipDuplicates = $options['skip_duplicates'] ?? true;
        $imported = 0;
        $skipped = 0;
        $errors = [];

        foreach ($csvData as $row) {
            try {
                if (empty($row[0])) {
                    $skipped++;
                    continue;
                }

                $title = $row[0];
                $website = $row[1] ?? '';

                // 检查重复
                $existing = Account::where('user_id', $userId)
                    ->where('title', $title)
                    ->where('website', $website)
                    ->find();

                if ($existing && $skipDuplicates) {
                    $skipped++;
                    $errors[] = "跳过重复: {$title}";
                    continue;
                }

                // 获取分类
                $categoryId = null;
                if (!empty($row[2])) {
                    $category = Category::where('name', $row[2])
                        ->where(function ($query) use ($userId) {
                            $query->where('user_id', $userId)
                                ->whereOr('user_id', null);
                        })
                        ->find();

                    if ($category) {
                        $categoryId = $category->id;
                    }
                }

                // 创建账号（注意：CSV导入的账号没有加密数据）
                Account::create([
                    'user_id' => $userId,
                    'category_id' => $categoryId,
                    'title' => $title,
                    'website' => $website,
                    'tags' => $row[3] ?? '',
                    'encrypt_method' => $row[4] ?? 'AES-256-GCM',
                ]);

                $imported++;

            } catch (Exception $e) {
                $skipped++;
                $errors[] = "导入失败: " . $e->getMessage();
            }
        }

        // 记录导入日志
        UserLog::record($userId, 'import_data', "导入CSV数据: 成功{$imported}条, 跳过{$skipped}条");

        return [
            'imported' => $imported,
            'skipped' => $skipped,
            'errors' => $errors
        ];
    }

    /**
     * 更新账号数据（从导入）
     */
    private function updateAccountFromImport($account, $data)
    {
        $updateData = [];

        if (isset($data['username_encrypted'])) {
            $updateData['username_encrypted'] = $data['username_encrypted'];
        }
        if (isset($data['password_encrypted'])) {
            $updateData['password_encrypted'] = $data['password_encrypted'];
        }
        if (isset($data['website'])) {
            $updateData['website'] = $data['website'];
        }
        if (isset($data['notes_encrypted'])) {
            $updateData['notes_encrypted'] = $data['notes_encrypted'];
        }
        if (isset($data['icon'])) {
            $updateData['icon'] = $data['icon'];
        }
        if (isset($data['tags'])) {
            $updateData['tags'] = $data['tags'];
        }
        if (isset($data['encrypt_method'])) {
            $updateData['encrypt_method'] = $data['encrypt_method'];
        }
        if (isset($data['expires_at'])) {
            $updateData['expires_at'] = $data['expires_at'];
        }

        if (!empty($updateData)) {
            $account->save($updateData);
        }
    }

    /**
     * 创建备份
     */
    public function createBackup($userId)
    {
        $exportData = $this->exportToJson($userId);

        $backupDir = runtime_path() . 'backups';
        if (!is_dir($backupDir)) {
            mkdir($backupDir, 0755, true);
        }

        $filename = "backup_{$userId}_" . date('YmdHis') . '.json';
        $filepath = $backupDir . DIRECTORY_SEPARATOR . $filename;

        file_put_contents($filepath, json_encode($exportData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));

        // 记录备份日志
        UserLog::record($userId, 'backup_data', "创建数据备份: {$filename}");

        return [
            'filename' => $filename,
            'filepath' => $filepath,
            'size' => filesize($filepath),
            'count' => $exportData['total_count']
        ];
    }

    /**
     * 恢复备份
     */
    public function restoreBackup($userId, $backupFile)
    {
        $backupDir = runtime_path() . 'backups';
        $filepath = $backupDir . DIRECTORY_SEPARATOR . $backupFile;

        if (!file_exists($filepath)) {
            throw new Exception('备份文件不存在');
        }

        $jsonContent = file_get_contents($filepath);
        $backupData = json_decode($jsonContent, true);

        if (!$backupData) {
            throw new Exception('备份文件格式错误');
        }

        $result = $this->importFromJson($userId, $backupData, [
            'skip_duplicates' => false,
            'update_existing' => true
        ]);

        // 记录恢复日志
        UserLog::record($userId, 'restore_data', "恢复数据备份: {$backupFile}");

        return $result;
    }

    /**
     * 列出用户的备份文件
     */
    public function listBackups($userId)
    {
        $backupDir = runtime_path() . 'backups';
        if (!is_dir($backupDir)) {
            return [];
        }

        $pattern = "backup_{$userId}_*.json";
        $files = glob($backupDir . DIRECTORY_SEPARATOR . $pattern);

        $backups = [];
        foreach ($files as $file) {
            $backups[] = [
                'filename' => basename($file),
                'size' => filesize($file),
                'created_at' => date('Y-m-d H:i:s', filemtime($file))
            ];
        }

        // 按时间倒序
        usort($backups, function ($a, $b) {
            return strcmp($b['created_at'], $a['created_at']);
        });

        return $backups;
    }

    /**
     * 删除备份文件
     */
    public function deleteBackup($userId, $filename)
    {
        // 验证文件名格式，防止目录遍历攻击
        if (!preg_match("/^backup_{$userId}_\d{14}\.json$/", $filename)) {
            throw new Exception('无效的备份文件名');
        }

        $backupDir = runtime_path() . 'backups';
        $filepath = $backupDir . DIRECTORY_SEPARATOR . $filename;

        if (!file_exists($filepath)) {
            throw new Exception('备份文件不存在');
        }

        unlink($filepath);

        // 记录删除日志
        UserLog::record($userId, 'delete_backup', "删除数据备份: {$filename}");

        return true;
    }
}
